#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <cerrno>
#include <cstring>
#include <cassert>
#include <cstdlib>
#include <netinet/in.h>
#include <strings.h>
#include <arpa/inet.h>
#include <cstdlib>
#include <cstdio>
#include <pthread.h>
enum
{
    SOCK_ERR = 1,
    BIND_ERR,
    USAGE_ERR
};
namespace Client
{
    using namespace std;
    class udpClient
    {
    public:
        udpClient(const string &serverIp, const uint16_t &serverPort)
            : _serverIp(serverIp), _serverPort(serverPort), _quit(false), _sockfd(-1)
        {
        }
        void initClient()
        {
            // 创建套接字
            _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
            if (_sockfd == -1)
            {
                cout << "socket error " << errno << " err string: " << strerror(errno) << endl;
                exit(SOCK_ERR);
            }
            cout << "socket create success " << endl;

            // 2. client要不要bind[必须要的]，client要不要显示的bind，需不需程序员自己bind？不需要！！！
            // 写服务器的是一家公司，写client是无数家公司 -- 由OS自动形成端口进行bind！-- OS在什么时候，如何bind
        }

        static void *recvMessage(void *args)
        {
            int sockfd = *(static_cast<int *>(args));
            pthread_detach(pthread_self());
            // 接受服务器的消息
            char temp[1024];
            while (true)
            {
                struct sockaddr_in server;
                socklen_t socklen = sizeof(server);
                ssize_t n = recvfrom(sockfd, temp, sizeof(temp) - 1, 0, (struct sockaddr *)&server, &socklen);
                if (n >= 0)
                    temp[n] = 0;
                // std::cout << "收到服务器的翻译: " << temp << endl;
                string ip = inet_ntoa(server.sin_addr);
                uint16_t port = ntohs(server.sin_port);

                cout << temp << endl;
            }
            return nullptr;
        }
        void run()
        {
            char buffer[1024];
            string message;
            struct sockaddr_in dest_addr;
            memset(&dest_addr, 0, sizeof(dest_addr));
            socklen_t addrlen = sizeof(dest_addr);
            dest_addr.sin_family = AF_INET;
            dest_addr.sin_addr.s_addr = inet_addr(_serverIp.c_str());
            dest_addr.sin_port = htons(_serverPort);

            pthread_create(&_reader, nullptr, recvMessage, &_sockfd);
            while (!_quit)
            {
                // cout << "please say# ";
                // cerr << "[blow@VM-4-11-centos udp]$ ";
                cerr << "enter# ";
                fgets(buffer, sizeof buffer, stdin);
                buffer[strlen(buffer) - 1] = 0; // 去掉输入的换行符

                // 发送信息的时候os自动绑定自己的ip和端口
                sendto(_sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)&dest_addr, addrlen);

                // // 接受服务器的翻译
                // char temp[1024];
                // struct sockaddr_in server;
                // socklen_t socklen = sizeof(server);
                // ssize_t n = recvfrom(_sockfd, temp, sizeof(temp) - 1, 0, (struct sockaddr*)&server, &socklen);
                // if(n >= 0) temp[n] = 0;
                // // std::cout << "收到服务器的翻译: " << temp << endl;
                // std::cout << "\n" << temp << endl;
            }
        }
        ~udpClient()
        {}

    private:
        string _serverIp;
        uint16_t _serverPort;
        int _sockfd;
        bool _quit;
        pthread_t _reader;
    };
}